// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

package org.jetbrains.kotlin.idea.quickfix

import com.intellij.codeInsight.intention.IntentionAction
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.addToStdlib.safeAs

internal object AddConstructorParameterFromSuperTypeCallFixFactory : KotlinSingleIntentionActionFactory() {
    override fun createAction(diagnostic: Diagnostic): IntentionAction? {
        val superTypeCallArgList = diagnostic.psiElement as? KtValueArgumentList ?: return null
        val superTypeCall = superTypeCallArgList.parent as? KtSuperTypeCallEntry ?: return null
        val containingClass = superTypeCall.containingClass() ?: return null

        val parameter = DiagnosticFactory.cast(diagnostic, Errors.NO_VALUE_FOR_PARAMETER).a
        val parameterIndex = parameter.index
        if (parameterIndex != superTypeCallArgList.arguments.size) return null
        val parameterName = parameter.name.render()
        val context = superTypeCallArgList.analyze(BodyResolveMode.PARTIAL)
        val constructor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, containingClass]?.safeAs<ClassDescriptor>()
            ?.constructors?.firstOrNull() ?: return null
        if (constructor.valueParameters.any { it.name.asString() == parameterName }) return null
        val superTypeCallParameters = superTypeCall.getResolvedCall(context)?.resultingDescriptor?.valueParameters
        val parameterType = superTypeCallParameters?.getOrNull(parameterIndex)?.type ?: parameter.type
        val parameterTypeSourceCode = IdeDescriptorRenderers.SOURCE_CODE_TYPES.renderType(parameterType)

        return AddConstructorParameterFromSuperTypeCallFix(superTypeCallArgList, parameterName, parameterTypeSourceCode).asIntention()
    }
}